// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BackupRunner.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace ExecutionTool
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;

    using ExecutionTool.Common;
    using ExecutionTool.CopyDatabase;
    using ExecutionTool.CopyOnPremises;
    using ExecutionTool.ImportExport;
    using ExecutionTool.Retention;

    public class BackupRunner : RunnerBase
    {
        #region Constructors and Destructors

        public BackupRunner(CommandLineOptions options)
            : base(options)
        {
        }

        #endregion

        #region Methods

        protected override void RunAction(Profile.Profile p)
        {
            /*
             * retention process (in parallel)
             * copy database
             * export
             * verify
             * on-premises copy
             * send notification
             */
            var processor = new RetentionProcessor(p, new StorageAdapter(), new OnPremisesAdapter());
            var retentionTask = Task.Factory.StartNew(() => processor.Process());
            retentionTask.ContinueWith(
                t => this.Logger.LogInformation("Successfully processed retention operations."), TaskContinuationOptions.OnlyOnRanToCompletion);

            CopyDatabaseStepInfo copyDatabaseStepInfo = null;
            if (p.Orchestration.CopyDatabase)
            {
                var step0 = new CopyDatabaseStep(p, this.SqlAzureAdapter);
                this.RunStep(step0, StepType.CopyDatabase, out copyDatabaseStepInfo);
            }

            if (p.Orchestration.Export)
            {
                var step1 = new ExportStep(p, this.ImportExportServiceAdapter, this.StorageAdapter, this.SqlAzureAdapter, null, copyDatabaseStepInfo);
                ExportStepInfo exportStepInfo;
                this.RunStep(step1, StepType.Export, out exportStepInfo);

                if (p.Orchestration.VerifyExport)
                {
                    var step3 = new ImportStep(
                        p, this.StorageAdapter, this.ImportExportServiceAdapter, this.SqlAzureAdapter, null, exportStepInfo.BlobName, exportStepInfo);
                    ImportStepInfo importStepInfo;
                    this.RunStep(step3, StepType.ImportVerification, out importStepInfo);
                }

                if (p.Orchestration.CopyToOnPremises)
                {
                    var step2 = new CopyOnPremisesStep(p, exportStepInfo, this.StorageAdapter, this.OnPremisesAdapter);
                    CopyOnPremisesStepInfo copyOnPremisesStepInfo;
                    this.RunStep(step2, StepType.CopyOnPremises, out copyOnPremisesStepInfo);
                }
            }

            var retentionError = false;

            try
            {
                retentionTask.Wait();
            }
            catch (Exception ex)
            {
                retentionError = true;
                this.Logger.LogWarning(ex.ToString(), ErrorCodes.RetentionProcessUnexpectedError);
            }

            // TODO: make sure retention process finished
            if (!this.Options.ToSuppressNotification && !string.IsNullOrWhiteSpace(p.Orchestration.NotificationList))
            {
                // TODO: send notification
            }

            this.Logger.LogInformation("Backup completed successfully.", 100);
        }

        protected override void TestConnectivityAction(Profile.Profile profile)
        {
            var tasks = new List<Task>();

            var sourceSqlAzureLocationTask = Task.Factory.StartNew(() => this.SqlAzureAdapter.TestConnection(profile.Source));
            tasks.Add(sourceSqlAzureLocationTask);

            if (profile.Orchestration.Export)
            {
                var importExportServiceTask =
                    Task.Factory.StartNew(
                        () =>
                        this.ImportExportServiceAdapter.TestConnection(
                            DataCenterMapper.GetDatacenterFromServerName(profile.Source.ServerName).Endpoint));
                tasks.Add(importExportServiceTask);

                var targetStorageLocationTask = Task.Factory.StartNew(() => this.StorageAdapter.TestConnection(profile.TargetAzureStorage));
                tasks.Add(targetStorageLocationTask);

                if (profile.Orchestration.VerifyExport)
                {
                    var verifyTask = Task.Factory.StartNew(() => this.SqlAzureAdapter.GetExistingDatabaseNames(profile.TargetSqlAzureVerification));
                    tasks.Add(verifyTask);
                    var importExportServiceTask2 =
                        Task.Factory.StartNew(
                            () =>
                            this.ImportExportServiceAdapter.TestConnection(
                                DataCenterMapper.GetDatacenterFromServerName(profile.TargetSqlAzureVerification.ServerName).Endpoint));
                    tasks.Add(importExportServiceTask2);
                }

                if (profile.Orchestration.CopyToOnPremises)
                {
                    var onpremisesTask = Task.Factory.StartNew(() => this.OnPremisesAdapter.TestConnection(profile.TargetOnPremisesLocation));
                    tasks.Add(onpremisesTask);
                }
            }

            Task.WaitAll(tasks.ToArray());
        }

        #endregion
    }
}
